package com.pinoc.design_pattern.templatetest;

/**
 * @author pinoc
 * @date 2023/5/4
 */
public class Lottery {
	// Different abstract behaviors for different types of lottery
	private BehaviorInterface concreteBehavior;

	public Lottery(BehaviorInterface concreteBehavior) {
		this.concreteBehavior = concreteBehavior;
	}

	// Lottery algorithm
	// Stable and unchanging algorithm steps
	public void run(Context ctx) throws Exception {
		// Concrete method: Check if the activity number (serial_no) exists and get the activity information
		if (checkSerialNo(ctx) != null) {
			throw new Exception(checkSerialNo(ctx));
		}

		// Concrete method: Check if the activity and session are currently in progress
		if (checkStatus(ctx) != null) {
			throw new Exception(checkStatus(ctx));
		}

		// Abstract method: Other parameter validations
		concreteBehavior.checkParams(ctx);

		// Concrete method: Check and deduct the activity lottery times
		if (checkTimesByAct(ctx) != null) {
			throw new Exception(checkTimesByAct(ctx));
		}

		// Concrete method: Check if the activity requires point consumption
		if (consumePointsByAct(ctx) != null) {
			throw new Exception(consumePointsByAct(ctx));
		}

		// Concrete method: Check and deduct the session lottery times
		if (checkTimesBySession(ctx) != null) {
			throw new Exception(checkTimesBySession(ctx));
		}

		// Concrete method: Get session prize information
		if (getPrizesBySession(ctx) != null) {
			throw new Exception(getPrizesBySession(ctx));
		}

		// Abstract method: Get node prize information
		concreteBehavior.getPrizesByNode(ctx);

		// Concrete method: Draw prizes
		if (drawPrizes(ctx) != null) {
			throw new Exception(drawPrizes(ctx));
		}

		// Concrete method: Check prize stock
		if (checkPrizesStock(ctx) != null) {
			throw new Exception(checkPrizesStock(ctx));
		}

		// Concrete method: Assemble prize information
		if (packagePrizeInfo(ctx) != null) {
			throw new Exception(packagePrizeInfo(ctx));
		}
	}

	// Concrete method: Check if the activity number (serial_no) exists and get the activity information
	private String checkSerialNo(Context ctx) {
		System.out.println(runFuncName() + "Check if the activity number (serial_no) exists and get the activity information...");
		return null;
	}

	// Concrete method: Check if the activity and session are currently in progress
	private String checkStatus(Context ctx) {
		System.out.println(runFuncName() + "Check if the activity and session are currently in progress...");
		return null;
	}

	// Concrete method: Check and deduct the activity lottery times
	private String checkTimesByAct(Context ctx) {
		System.out.println(runFuncName() + "Check and deduct the activity lottery times...");
		return null;
	}

	// Concrete method: Check if the activity requires point consumption
	private String consumePointsByAct(Context ctx) {
		System.out.println(runFuncName() + "Check if the activity requires point consumption...");
		return null;
	}

	// Concrete method: Check and deduct the session lottery times
	private String checkTimesBySession(Context ctx) {
		System.out.println(runFuncName() + "Check and deduct the session lottery times...");
		return null;
	}

	// Concrete method: Get session prize information
	private String getPrizesBySession(Context ctx) {
		System.out.println(runFuncName() + "Get session prize information...");
		return null;
	}

	// Concrete method: Draw prizes
	private String drawPrizes(Context ctx) {
		System.out.println(runFuncName() + "Draw prizes...");
		return null;
	}

	// Concrete method: Check prize stock
	private String checkPrizesStock(Context ctx) {
		System.out.println(runFuncName() + "Check prize stock...");
		return null;
	}

	// Concrete method: Assemble prize information
	private String packagePrizeInfo(Context ctx) {
		System.out.println(runFuncName() + "Assemble prize information...");
		return null;
	}

	// Get the name of the calling method
	private static String runFuncName() {
		StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
		if (stackTrace.length >= 3) {
			return stackTrace[2].getMethodName();
		} else {
			return "";
		}
	}

	public static void main(String[] args) throws Exception {
		Lottery lottery = new Lottery(new TimeDraw());
		lottery.run(new Context(new ActInfo(Constants.ACT_TYPE_TIME)));
	}
}
